package logger

import (
	"io"
	"log"
	"os"
	"path"

	"github.com/rs/zerolog"
	lumberjack "gopkg.in/natefinch/lumberjack.v2"
)

type LogLevel int

const (
	Debug LogLevel = iota
	Info
	Warn
	Error
	Fatal
)

type LogConfig struct {
	Level          LogLevel
	ConsoleEnabled bool // is log to console
	FileEnabled    bool // is log to file
	LogDir         string
	FileName       string
	MaxSize        int // MaxSize the max size in MB of the logfile before it's rolled
	MaxBackups     int // MaxBackups the max number of rolled files to keep
	MaxAge         int // MaxAge the max age in days to keep a logfile
}

func NewLogger(lc LogConfig) *zerolog.Logger {
	zerolog.TimeFieldFormat = "2006-01-02 15:04:05.000000"
	setLogLevel(lc.Level)
	mw := getLoggerWriters(lc)

	logger := zerolog.New(mw).With().Timestamp().Caller().Logger()

	return &logger
}

func setLogLevel(level LogLevel) {

	switch level {
	case Debug:
		zerolog.SetGlobalLevel(zerolog.DebugLevel)
	case Info:
		zerolog.SetGlobalLevel(zerolog.InfoLevel)
	case Warn:
		zerolog.SetGlobalLevel(zerolog.WarnLevel)
	case Error:
		zerolog.SetGlobalLevel(zerolog.ErrorLevel)
	case Fatal:
		zerolog.SetGlobalLevel(zerolog.FatalLevel)
	default:
		zerolog.SetGlobalLevel(zerolog.DebugLevel)
	}
}

func getLoggerWriters(lc LogConfig) io.Writer {
	var writers []io.Writer

	if lc.ConsoleEnabled {
		writers = append(writers, zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: "2006-01-02 15:04:05.000000"})
	}

	if lc.FileEnabled {
		writers = append(writers, newRollingFile(lc))
	}

	return io.MultiWriter(writers...)
}

func newRollingFile(lc LogConfig) io.Writer {
	if err := os.MkdirAll(lc.LogDir, 0744); err != nil {
		log.Fatal("can't create log directory")
		return nil
	}

	if lc.MaxBackups == 0 {
		lc.MaxBackups = 10
	}

	if lc.MaxSize == 0 {
		lc.MaxSize = 5
	}

	if lc.MaxAge == 0 {
		lc.MaxAge = 7
	}

	return &lumberjack.Logger{
		Filename:   path.Join(lc.LogDir, lc.FileName),
		MaxBackups: lc.MaxBackups, // files
		MaxSize:    lc.MaxSize,    // megabytes
		MaxAge:     lc.MaxAge,     // days

	}
}
